package com.xiaoshuidi.cloud.module.report.xxljob;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderTypeEnum;
import com.xiaoshuidi.cloud.module.contract.enums.contract.ContractSettlementTypeEnum;
import com.xiaoshuidi.cloud.module.report.constant.FlowTypeEnum;
import com.xiaoshuidi.cloud.module.report.constant.RoomHouseReserveStatus;
import com.xiaoshuidi.cloud.module.report.dal.DO.*;
import com.xiaoshuidi.cloud.module.report.dal.DO.report.*;
import com.xiaoshuidi.cloud.module.report.dal.dto.FinanceMoneyFlowDTO;
import com.xiaoshuidi.cloud.module.report.dal.mapper.*;
import com.xiaoshuidi.cloud.module.report.dal.mapper.report.*;
import com.xiaoshuidi.cloud.module.report.utils.ThreadPoolUtils;
import com.xiaoshuidi.cloud.module.report.xxljob.PO.CollectionHandlePO;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * 收款汇总定时任务
 */
@Component
@Slf4j
public class CollectionHandleJob {

    @Resource
    private ContractRoomMapper contractRoomMapper;
    @Resource
    private ContractRentorderMapper contractRentorderMapper;
    @Resource
    private RoomHouseMapper roomHouseMapper;
    @Resource
    private RoomHouseReserveMapper roomHouseReserveMapper;
    @Resource
    private ReportRentDepositSummaryMapper reportRentDepositSummaryMapper;
    @Resource
    private FinanceMoneyFlowMapper financeMoneyFlowMapper;
    @Resource
    private ReportReserveSummaryMapper reportReserveSummaryMapper;
    @Resource
    private ReportFeeSummaryMapper reportFeeSummaryMapper;
    @Resource
    private ContractOrderfeesMapper contractOrderfeesMapper;
    @Resource
    private ContractSettlementMapper contractSettlementMapper;
    @Resource
    private ContractSettlementDetailMapper contractSettlementDetailMapper;
    @Resource
    private ReportCollectionSummaryMapper reportCollectionSummaryMapper;
    @Resource
    private ReportReceivableCheckMapper reportReceivableCheckMapper;



    /**
     * 租金押金收款汇总
     */
    @XxlJob("rent-deposit-summary")
    @TenantIgnore
    public void execute() {
        //默认获取昨天所有的账单流水
        String params = XxlJobHelper.getJobParam();
        CollectionHandlePO paramPo = new CollectionHandlePO();
        if(StringUtils.isNotBlank(params)){
            try {
                paramPo = JSONObject.parseObject(params, CollectionHandlePO.class);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }else {
            paramPo.setMinusDay(1);
        }
        // 默认合同账单
        paramPo.setType(0);
        Long totalNum = financeMoneyFlowMapper.countSummaryByParam(paramPo);
        if (totalNum <= 1000) {
            List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
            if (CollectionUtils.isNotEmpty(moneyFlowList)){
                handlerDetails(moneyFlowList);
            }
        } else {
            //分1000一批处理
            int num = totalNum.intValue()/1000 + 1 ;
            CountDownLatch latch = new CountDownLatch(num);
            for (int i = 0; i < num; i++) {
                paramPo.setPageNo(i * 1000);
                paramPo.setPageSize(1000);
                List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
                ThreadPoolUtils.poolExecutor.execute(()->{
                    handlerDetails(moneyFlowList);
                    latch.countDown();
                });
            }
            try {
                log.info("---------------处理租金及押金收款汇总完成-------------");
                latch.await();
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }
            
        }
    }

    private void handlerDetails(List<FinanceMoneyFlowDTO> moneyFlowList) {
        List<ReportRentDepositSummaryDO> summaryList = summaryRentDeposit(moneyFlowList);
        if (CollectionUtils.isNotEmpty(summaryList)){
            // 校验重复
            List<String> flowNoList = summaryList.stream().map(ReportRentDepositSummaryDO::getFlowNo).collect(Collectors.toList());
            List<Long> existFlowNos = reportRentDepositSummaryMapper.selectExistOrder(flowNoList);
            if (CollectionUtils.isNotEmpty(existFlowNos)){
                // 过滤重复数据后插入
                summaryList = summaryList.stream().filter(s -> !existFlowNos.contains(s.getOrderId())).collect(Collectors.toList());
            }
            reportRentDepositSummaryMapper.insertBatch(summaryList);
        }
    }

    private List<ReportRentDepositSummaryDO> summaryRentDeposit(List<FinanceMoneyFlowDTO> moneyFlowList){
        List<Long> contratIds = moneyFlowList.stream()
                .map(FinanceMoneyFlowDTO::getContractId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contratIds)){
            return null;
        }
        // 查询合同信息
        List<ContractRoomDO> contractRoomList = contractRoomMapper.selectList(ContractRoomDO::getId, contratIds);
        if (CollectionUtils.isEmpty(contractRoomList)){
            return null;
        }
        List<Long> roomIds = contractRoomList.stream()
                .map(ContractRoomDO::getRoomId)
                .distinct()
                .collect(Collectors.toList());
        // 查询房源信息
        List<RoomHouseDO> roomHouseList = roomHouseMapper.selectByIds(roomIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            return null;
        }
        List<ReportRentDepositSummaryDO> summaryList = new ArrayList<>();
        for (FinanceMoneyFlowDTO moneyFlow : moneyFlowList) {
            ReportRentDepositSummaryDO summaryDO = new ReportRentDepositSummaryDO();
            summaryDO.setOrderId(moneyFlow.getOrderId());
            summaryDO.setFlowNo(moneyFlow.getFlowNo());
            summaryDO.setPayMethod(moneyFlow.getPayMethod());
            summaryDO.setPaymentDate(moneyFlow.getTradeTime());
            summaryDO.setTenantId(moneyFlow.getTenantId());
            Double handlingFeeRate = 0.00;
            if (moneyFlow.getPayMethod().contains("微信") || moneyFlow.getPayMethod().contains("支付宝")){
                handlingFeeRate = 0.0025;
            }
            summaryDO.setHandlingFeeRate(handlingFeeRate);
            BigDecimal receivableRent = moneyFlow.getRentAmount()
                    .subtract(Objects.nonNull(moneyFlow.getDiscountAmount())?moneyFlow.getDiscountAmount():BigDecimal.ZERO)
                    .subtract(Objects.nonNull(moneyFlow.getCouponDiscount())?moneyFlow.getCouponDiscount():BigDecimal.ZERO);
            summaryDO.setReceivableRent(receivableRent);
            summaryDO.setReceivableDeposit(moneyFlow.getDepositAmount());
            // 合同信息
            ContractRoomDO contractRoomDO = contractRoomList.stream()
                    .filter(cr -> cr.getId().equals(moneyFlow.getContractId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(contractRoomDO)){
                continue;
            }
            // 续租或换房合同 & 首期账单
            if (Objects.nonNull(contractRoomDO.getFromId()) && !(Long.valueOf("0").equals(contractRoomDO.getFromId())) && moneyFlow.getNum() == 1){
                // 查询原合同信息
                ContractRoomDO fromContractRoom = contractRoomMapper.selectOne(ContractRoomDO::getId, contractRoomDO.getFromId());
                summaryDO.setReceivableDeposit(BigDecimal.ZERO);
                // 押金不同
                if (Objects.nonNull(fromContractRoom) && fromContractRoom.getDeposit().compareTo(summaryDO.getReceivableDeposit()) != 0){
                    BigDecimal subtract = summaryDO.getReceivableDeposit().subtract(fromContractRoom.getDeposit());
                    if (subtract.compareTo(BigDecimal.ZERO) > 0){
                        summaryDO.setReceivableDeposit(subtract);
                    }
                }
            }

            // 实收金额
            summaryDO.setActualAmount(Objects.nonNull(moneyFlow.getTradeAmount())?moneyFlow.getTradeAmount():BigDecimal.ZERO);
            // 实收租金 = 实收金额 - 应收押金
            summaryDO.setActualRent(summaryDO.getActualAmount().subtract(summaryDO.getReceivableDeposit()));
            // 收款手续费 = 实收金额 * 手续费率
            summaryDO.setCollectionFee(summaryDO.getActualAmount().multiply(BigDecimal.valueOf(handlingFeeRate)));


            summaryDO.setRoomId(contractRoomDO.getRoomId());
            summaryDO.setRoomName(contractRoomDO.getRoomName());
            summaryDO.setCustomerName(contractRoomDO.getCustomerName());
            summaryDO.setMemberId(contractRoomDO.getMemberId());

            // 房源信息
            RoomHouseDO roomHouseDO = roomHouseList.stream()
                    .filter(r -> r.getId().equals(contractRoomDO.getRoomId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            summaryDO.setSpace(roomHouseDO.getSpace());

            summaryDO.setReserveRentAmount(BigDecimal.ZERO);
            // 首期账单可能存在定金转租金
            if (moneyFlow.getNum() == 1){
                // 查询预定信息
                LambdaQueryWrapper<RoomHouseReserveDO> reserveQueryWrapper = new LambdaQueryWrapper<>();
                reserveQueryWrapper.eq(RoomHouseReserveDO::getStatus, RoomHouseReserveStatus.SINGED.getCode());
                reserveQueryWrapper.eq(RoomHouseReserveDO::getBookerPhone, contractRoomDO.getCustomerPhone());
                reserveQueryWrapper.eq(RoomHouseReserveDO::getRoomHouseId, roomHouseDO.getId());
                List<RoomHouseReserveDO> roomHouseReserveDOS = roomHouseReserveMapper.selectList(reserveQueryWrapper);
                if (CollectionUtils.isNotEmpty(roomHouseReserveDOS)){
                    RoomHouseReserveDO roomHouseReserveDO = roomHouseReserveDOS.get(0);
                    summaryDO.setReserveRentAmount(roomHouseReserveDO.getDeposit());
                }
            }
            summaryList.add(summaryDO);
        }
        return summaryList;
    }


    /**
     * 定金统计
     */
    @XxlJob("reserve-summary")
    @TenantIgnore
    public void reserveExecute() {
        //默认获取昨天所有的预定账单
        String params = XxlJobHelper.getJobParam();
        CollectionHandlePO paramPo = new CollectionHandlePO();
        if(StringUtils.isNotBlank(params)){
            try {
                paramPo = JSONObject.parseObject(params, CollectionHandlePO.class);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }else {
            paramPo.setMinusDay(1);
        }
        // 处理定金统计表里没有的预定单数据
        Long totalNum = roomHouseReserveMapper.countSummaryListByParam(paramPo);
        if (totalNum <= 1000) {
            List<RoomHouseReserveDO> roomHouseReserveList = roomHouseReserveMapper.querySummaryListByParam(paramPo);
            if (CollectionUtils.isNotEmpty(roomHouseReserveList)){
                handlerReserve(roomHouseReserveList);
            }
        } else {
            //分1000一批处理
            int num = totalNum.intValue()/1000 + 1 ;
            CountDownLatch latch = new CountDownLatch(num);
            for (int i = 0; i < num; i++) {
                paramPo.setPageNo(i * 1000);
                paramPo.setPageSize(1000);
                List<RoomHouseReserveDO> roomHouseReserveList = roomHouseReserveMapper.querySummaryListByParam(paramPo);
                ThreadPoolUtils.poolExecutor.execute(()->{
                    handlerReserve(roomHouseReserveList);
                    latch.countDown();
                });
            }
            try {
                log.info("---------------批量处理定金统计完成111-------------");
                latch.await();
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }
        }

        // 处理定金统计表里有的，但从已支付变为已签约的数据
        List<RoomHouseReserveDO> reserveUpdateList = roomHouseReserveMapper.queryUpdateSummaryList();
        List<Long> reserveIds = reserveUpdateList.stream().map(RoomHouseReserveDO::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(reserveIds)){
            reportReserveSummaryMapper.updateBatchSigned(reserveIds);
        }

        log.info("---------------批量处理定金统计完成222-------------");
    }

    private void handlerReserve(List<RoomHouseReserveDO> roomHouseReserveList) {
        List<Long> roomIds = roomHouseReserveList.stream()
                .map(RoomHouseReserveDO::getRoomHouseId)
                .distinct()
                .collect(Collectors.toList());
        // 查询房源信息
        List<RoomHouseDO> roomHouseList = roomHouseMapper.selectByIds(roomIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            return;
        }

        List<Long> moneyFlowIds = roomHouseReserveList.stream()
                .map(RoomHouseReserveDO::getPaymentId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(moneyFlowIds)){
            return;
        }
        // 查询流水信息
        List<FinanceMoneyFlowDO> moneyFlowList = financeMoneyFlowMapper.selectList(FinanceMoneyFlowDO::getId, moneyFlowIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            return;
        }

        List<ReportReserveSummaryDO> summaryList = new ArrayList<>();
        for (RoomHouseReserveDO reserve : roomHouseReserveList) {
            ReportReserveSummaryDO reserveSummary = new ReportReserveSummaryDO();
            reserveSummary.setReserveId(reserve.getId());
            reserveSummary.setRoomId(reserve.getRoomHouseId());
            reserveSummary.setCustomerName(reserve.getBooker());
            reserveSummary.setMemberId(reserve.getBookerId());
            reserveSummary.setPaymentDate(reserve.getPaymentTime());
            reserveSummary.setActualAmount(reserve.getDeposit());
            reserveSummary.setTenantId(reserve.getTenantId());
            if (RoomHouseReserveStatus.SINGED.getCode().equals(reserve.getStatus())){
                reserveSummary.setReserveRentAmount(reserve.getDeposit());
            }

            // 房源信息
            RoomHouseDO roomHouseDO = roomHouseList.stream()
                    .filter(r -> r.getId().equals(reserve.getRoomHouseId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            reserveSummary.setSpace(roomHouseDO.getSpace());

            // 流水信息
            FinanceMoneyFlowDO moneyFlowDO = moneyFlowList.stream()
                    .filter(r -> r.getId().equals(reserve.getPaymentId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            reserveSummary.setRoomName(moneyFlowDO.getRoomName());
            reserveSummary.setPayMethod(moneyFlowDO.getPayMethod());
            Double handlingFeeRate = 0.00;
            if (StringUtils.equals(moneyFlowDO.getPayMethod(), "微信") || StringUtils.equals(moneyFlowDO.getPayMethod(), "支付宝")){
                handlingFeeRate = 0.0025;
            }
            reserveSummary.setHandlingFeeRate(handlingFeeRate);
            // 收款手续费 = 实收金额 * 手续费率
            reserveSummary.setCollectionFee(reserveSummary.getActualAmount().multiply(BigDecimal.valueOf(handlingFeeRate)));
            summaryList.add(reserveSummary);
        }
        reportReserveSummaryMapper.insertBatch(summaryList);
    }



    /**
     * 水电费等收款汇总
     */
    @XxlJob("fee-summary")
    @TenantIgnore
    public void feeExecute() {
        //默认获取昨天所有的账单
        String params = XxlJobHelper.getJobParam();
        CollectionHandlePO paramPo = new CollectionHandlePO();
        if(StringUtils.isNotBlank(params)){
            try {
                paramPo = JSONObject.parseObject(params, CollectionHandlePO.class);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }else {
            paramPo.setMinusDay(1);
        }
        // type = 1 meter  抄表账单
        paramPo.setType(1);
        Long totalNum = financeMoneyFlowMapper.countSummaryByParam(paramPo);
        if (totalNum <= 1000) {
            List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
            if (CollectionUtils.isNotEmpty(moneyFlowList)){
                handlerFee(moneyFlowList);
            }
        } else {
            //分1000一批处理
            int num = totalNum.intValue()/1000 + 1 ;
            CountDownLatch latch = new CountDownLatch(num);
            for (int i = 0; i < num; i++) {
                paramPo.setPageNo(i * 1000);
                paramPo.setPageSize(1000);
                List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
                ThreadPoolUtils.poolExecutor.execute(()->{
                    handlerFee(moneyFlowList);
                    latch.countDown();
                });
            }
            try {
                log.info("---------------处理租金及押金收款汇总完成-------------");
                latch.await();
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }

        }
    }

    private void handlerFee(List<FinanceMoneyFlowDTO> moneyFlowList) {
        List<ReportFeeSummaryDO> summaryList = summaryFee(moneyFlowList);
        if (CollectionUtils.isNotEmpty(summaryList)){
            // 校验重复
            List<String> flowNoList = summaryList.stream().map(ReportFeeSummaryDO::getFlowNo).collect(Collectors.toList());
            List<Long> existFlowNos = reportFeeSummaryMapper.selectExistOrder(flowNoList);
            if (CollectionUtils.isNotEmpty(existFlowNos)){
                // 过滤重复数据后插入
                summaryList = summaryList.stream().filter(s -> !existFlowNos.contains(s.getOrderId())).collect(Collectors.toList());
            }
            reportFeeSummaryMapper.insertBatch(summaryList);
        }
    }
    private List<ReportFeeSummaryDO> summaryFee(List<FinanceMoneyFlowDTO> moneyFlowList){
        List<Long> contratIds = moneyFlowList.stream()
                .map(FinanceMoneyFlowDTO::getContractId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contratIds)){
            return null;
        }
        // 查询合同信息
        List<ContractRoomDO> contractRoomList = contractRoomMapper.selectList(ContractRoomDO::getId, contratIds);
        if (CollectionUtils.isEmpty(contractRoomList)){
            return null;
        }
        List<Long> roomIds = contractRoomList.stream()
                .map(ContractRoomDO::getRoomId)
                .distinct()
                .collect(Collectors.toList());
        // 查询房源信息
        List<RoomHouseDO> roomHouseList = roomHouseMapper.selectByIds(roomIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            return null;
        }
        // 查询账单明细
        List<Long> orderIds = moneyFlowList.stream()
                .map(FinanceMoneyFlowDTO::getOrderId)
                .distinct()
                .collect(Collectors.toList());
        List<ContractOrderFeesDO> contractOrderFeesList = contractOrderfeesMapper.selectByOrderIds(orderIds);
        if (CollectionUtils.isEmpty(contractOrderFeesList)){
            return null;
        }
        List<ReportFeeSummaryDO> summaryList = new ArrayList<>();
        for (FinanceMoneyFlowDTO moneyFlow : moneyFlowList) {
            ReportFeeSummaryDO summaryDO = new ReportFeeSummaryDO();
            summaryDO.setOrderId(moneyFlow.getOrderId());
            summaryDO.setFlowNo(moneyFlow.getFlowNo());
            summaryDO.setPayMethod(moneyFlow.getPayMethod());
            summaryDO.setPaymentDate(moneyFlow.getTradeTime());
            summaryDO.setTenantId(moneyFlow.getTenantId());
            Double handlingFeeRate = 0.00;
            if (StringUtils.equals(moneyFlow.getPayMethod(), "微信") || StringUtils.equals(moneyFlow.getPayMethod(), "支付宝")){
                handlingFeeRate = 0.0025;
            }
            summaryDO.setHandlingFeeRate(handlingFeeRate);
            summaryDO.setActualAmount(Objects.nonNull(moneyFlow.getTradeAmount())?moneyFlow.getTradeAmount():BigDecimal.ZERO);
            // 收款手续费 = 实收金额 * 手续费率
            summaryDO.setCollectionFee(summaryDO.getActualAmount().multiply(BigDecimal.valueOf(handlingFeeRate)));

            // 合同信息
            ContractRoomDO contractRoomDO = contractRoomList.stream()
                    .filter(cr -> cr.getId().equals(moneyFlow.getContractId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(contractRoomDO)){
                continue;
            }
            summaryDO.setRoomId(contractRoomDO.getRoomId());
            summaryDO.setRoomName(contractRoomDO.getRoomName());
            summaryDO.setCustomerName(contractRoomDO.getCustomerName());
            summaryDO.setMemberId(contractRoomDO.getMemberId());

            // 房源信息
            RoomHouseDO roomHouseDO = roomHouseList.stream()
                    .filter(r -> r.getId().equals(contractRoomDO.getRoomId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            summaryDO.setSpace(roomHouseDO.getSpace());

            List<ContractOrderFeesDO> orderFeesList = contractOrderFeesList.stream()
                    .filter(f -> f.getOrderId().equals(moneyFlow.getId()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(orderFeesList)){
                continue;
            }
            BigDecimal waterFee = BigDecimal.ZERO;
            BigDecimal electFee = BigDecimal.ZERO;
            BigDecimal parkFee = BigDecimal.ZERO;
            BigDecimal otherFee = BigDecimal.ZERO;
            for (ContractOrderFeesDO orderFeesDO : orderFeesList) {
                if (orderFeesDO.getFeeName().contains("水费")){
                    waterFee = waterFee.add(orderFeesDO.getPaidAmount());
                } else if (orderFeesDO.getFeeName().contains("电费")) {
                    electFee = electFee.add(orderFeesDO.getPaidAmount());
                } else if (orderFeesDO.getFeeName().contains("停车费")) {
                    parkFee = parkFee.add(orderFeesDO.getPaidAmount());
                } else {
                    otherFee = otherFee.add(orderFeesDO.getPaidAmount());
                }
            }
            summaryDO.setWaterFeeAmount(waterFee);
            summaryDO.setElectricityFeeAmount(electFee);
            summaryDO.setParkFeeAmount(parkFee);
            summaryDO.setOtherFeeAmount(otherFee);
            summaryList.add(summaryDO);
        }
        return summaryList;
    }


    /**
     * 所有收款汇总
     */
    @XxlJob("all-summary")
    @TenantIgnore
    public void allExecute() {
        //默认获取昨天所有的账单 和退租清算单
        String params = XxlJobHelper.getJobParam();
        CollectionHandlePO paramPo = new CollectionHandlePO();
        if(StringUtils.isNotBlank(params)){
            try {
                paramPo = JSONObject.parseObject(params, CollectionHandlePO.class);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }else {
            paramPo.setMinusDay(1);
        }
//        // type = 2 合同账单 和 抄表账单
//        paramPo.setType(2);
//        List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
//        // 清算单
//        List<ContractSettlementDO> settlementList = contractSettlementMapper.selectListForSummary(paramPo);
//        handlerAll(moneyFlowList, settlementList);
        handlerAll2(paramPo);
        log.info("---------------处理所有收款汇总完成-------------");
    }
    private List<ReportRentDepositSummaryDO> handleRentDeposit(CollectionHandlePO paramPo){
        paramPo.setType(0);
        List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
        return summaryRentDeposit(moneyFlowList);
    }
    private List<ReportFeeSummaryDO> handleFee(CollectionHandlePO paramPo){
        paramPo.setType(1);
        List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
        return summaryFee(moneyFlowList);
    }
    private void handlerAll2(CollectionHandlePO paramPo) {
        // 租金押金
        List<ReportRentDepositSummaryDO> summaryRentDepositList = handleRentDeposit(paramPo);
        // 水电杂费
        List<ReportFeeSummaryDO> summaryFeeList = handleFee(paramPo);
        // 清算单
        List<ContractSettlementDO> settlementList = contractSettlementMapper.selectListForSummary(paramPo);
        // 查询清算单明细
        List<ContractSettlementDetailDO> contractSettlementDetails = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(settlementList)){
            List<Long> settlementIds = settlementList.stream()
                    .map(ContractSettlementDO::getId)
                    .distinct()
                    .collect(Collectors.toList());
            contractSettlementDetails = contractSettlementDetailMapper.selectByOrderIds(settlementIds);
        }

        // 房间号+承租人 分组
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Map<String, List<ReportRentDepositSummaryDO>> summaryRentDepositMap = null;
        if (CollectionUtils.isNotEmpty(summaryRentDepositList)){
            summaryRentDepositMap = summaryRentDepositList.stream()
                    .filter(m -> Objects.nonNull(m.getRoomId()))
                    .collect(Collectors.groupingBy(m -> m.getRoomId() + "-" + m.getCustomerName() + "-" + m.getPaymentDate().format(formatter)));
        }
        Map<String, List<ReportFeeSummaryDO>> summaryFeeMap = null;
        if (CollectionUtils.isNotEmpty(summaryFeeList)){
            summaryFeeMap = summaryFeeList.stream()
                    .filter(m -> Objects.nonNull(m.getRoomId()))
                    .collect(Collectors.groupingBy(m -> m.getRoomId() + "-" + m.getCustomerName() + "-" + m.getPaymentDate().format(formatter)));
        }
        Map<String, List<ContractSettlementDO>> settlementMap = null;
        if (CollectionUtils.isNotEmpty(settlementList)){
            settlementMap = settlementList.stream()
                    .filter(s -> Objects.nonNull(s.getRoomId()))
                    .collect(Collectors.groupingBy(s -> s.getRoomId() + "-" + s.getCustomerName() + "-" + s.getCreateTime().format(formatter)));
        }
        List<String> roomRenterList = new ArrayList<>();
        if (summaryRentDepositMap != null && !summaryRentDepositMap.isEmpty()){
            roomRenterList.addAll(new ArrayList<>(summaryRentDepositMap.keySet()));
        }
        if (summaryFeeMap != null && !summaryFeeMap.isEmpty()){
            roomRenterList.addAll(new ArrayList<>(summaryFeeMap.keySet()));
        }
        if (settlementMap != null && !settlementMap.isEmpty()){
            roomRenterList.addAll(new ArrayList<>(settlementMap.keySet()));
        }
        // 去重
        Set<String> roomRenterSet = new LinkedHashSet<>(roomRenterList);
        roomRenterList = new ArrayList<>(roomRenterSet);
        List<ReportCollectionSummaryDO> summaryList = new ArrayList<>();
        for (String roomRenter : roomRenterList) {
            ReportCollectionSummaryDO summaryDO = new ReportCollectionSummaryDO();
            String[] split = roomRenter.split("-");
            Long roomId = Long.valueOf(split[0]);
            String renter = split[1];
            summaryDO.setRoomId(roomId);
            summaryDO.setCustomerName(renter);

            BigDecimal actualRent = BigDecimal.ZERO;
            BigDecimal actualDeposit = BigDecimal.ZERO;
            if (summaryRentDepositMap != null && !summaryRentDepositMap.isEmpty()){
                List<ReportRentDepositSummaryDO> summaryRentDepositMapList = summaryRentDepositMap.get(roomRenter);
                if (CollectionUtils.isNotEmpty(summaryRentDepositMapList)){
                    for (ReportRentDepositSummaryDO depositSummaryDO : summaryRentDepositMapList) {
                        actualRent = actualRent.add(depositSummaryDO.getActualRent());
                        actualDeposit = actualDeposit.add(depositSummaryDO.getReceivableDeposit());
                    }
                    ReportRentDepositSummaryDO summaryDO1 = summaryRentDepositMapList.get(0);
                    summaryDO.setMemberId(summaryDO1.getMemberId());
                    summaryDO.setTenantId(summaryDO1.getTenantId());
                    summaryDO.setSpace(summaryDO1.getSpace());
                    summaryDO.setPaymentDate(summaryDO1.getPaymentDate());
                    summaryDO.setRoomName(summaryDO1.getRoomName());
                }
            }

            summaryDO.setActualRent(actualRent);
            summaryDO.setActualDeposit(actualDeposit);
            summaryDO.setActualRentDeposit(actualRent.add(actualDeposit));

            BigDecimal actualWater = BigDecimal.ZERO;
            BigDecimal actualElectric = BigDecimal.ZERO;
            BigDecimal actualPark = BigDecimal.ZERO;
            BigDecimal actualOther = BigDecimal.ZERO;
            if (summaryFeeMap != null && !summaryFeeMap.isEmpty()){
                // 杂费汇总
                List<ReportFeeSummaryDO> summaryFeeMapList = summaryFeeMap.get(roomRenter);
                if (CollectionUtils.isNotEmpty(summaryFeeMapList)){
                    for (ReportFeeSummaryDO feeSummaryDO : summaryFeeMapList) {
                        actualWater = actualWater.add(feeSummaryDO.getWaterFeeAmount());
                        actualElectric = actualElectric.add(feeSummaryDO.getElectricityFeeAmount());
                        actualPark = actualPark.add(feeSummaryDO.getParkFeeAmount());
                        actualOther = actualOther.add(feeSummaryDO.getOtherFeeAmount());
                    }
                    ReportFeeSummaryDO summaryDO2 = summaryFeeMapList.get(0);
                    summaryDO.setMemberId(summaryDO2.getMemberId());
                    summaryDO.setTenantId(summaryDO2.getTenantId());
                    summaryDO.setSpace(summaryDO2.getSpace());
                    summaryDO.setPaymentDate(summaryDO2.getPaymentDate());
                    summaryDO.setRoomName(summaryDO2.getRoomName());
                }
            }
            summaryDO.setActualWater(actualWater);
            summaryDO.setActualElectric(actualElectric);
            summaryDO.setActualPark(actualPark);
            summaryDO.setActualOther(actualOther);
            summaryDO.setActualFeeAmount(actualWater.add(actualElectric).add(actualPark).add(actualOther));

            BigDecimal actualRefundRent = BigDecimal.ZERO;
            BigDecimal actualRefundDeposit = BigDecimal.ZERO;
            // 清算单
            summaryDO.setActualRefundRent(BigDecimal.ZERO);
            summaryDO.setActualRefundDeposit(BigDecimal.ZERO);
            summaryDO.setActualRefundRentDeposit(BigDecimal.ZERO);
            if (settlementMap != null && !settlementMap.isEmpty() && CollectionUtils.isNotEmpty(contractSettlementDetails)){
                List<ContractSettlementDO> contractSettlementDOS = settlementMap.get(roomRenter);
                if (CollectionUtils.isNotEmpty(contractSettlementDOS)){
                    ContractSettlementDO contractSettlementDO = contractSettlementDOS.get(0);
                    // 实退租金、押金
                    List<ContractSettlementDetailDO> settlementRentDepositList = contractSettlementDetails.stream()
                            .filter(s -> (FlowTypeEnum.OUT.getCode().equals(s.getFlowType())) && s.getSettlementId().longValue() == contractSettlementDO.getId().longValue()
                                    && ((s.getFeeId().longValue() == 1L) || (s.getFeeId().longValue() == 2L)))
                            .collect(Collectors.toList());
                    for (ContractSettlementDetailDO contractSettlementDetailDO : settlementRentDepositList) {
                        if (1L == contractSettlementDetailDO.getFeeId().longValue()){
                            actualRefundRent = actualRefundRent.add(contractSettlementDetailDO.getRefundableAmount());
                        }
                        if (2L == contractSettlementDetailDO.getFeeId().longValue()){
                            actualRefundDeposit = actualRefundDeposit.add(contractSettlementDetailDO.getRefundableAmount());
                        }
                    }
                    if (Objects.isNull(summaryDO.getRoomName())){
                        ContractSettlementDO settlementDO = contractSettlementDOS.get(0);
                        summaryDO.setTenantId(settlementDO.getTenantId());
                        summaryDO.setPaymentDate(settlementDO.getCreateTime());
                        summaryDO.setRoomName(settlementDO.getRoomName());
                        Long contractId = settlementDO.getContractId();
                        ContractRoomDO contractRoomDO = contractRoomMapper.selectOne(ContractRoomDO::getId, contractId);
                        if (Objects.nonNull(contractRoomDO)){
                            summaryDO.setMemberId(contractRoomDO.getMemberId());
                        }
                        Long settlementRoomId = settlementDO.getRoomId();
                        RoomHouseDO roomHouseDO = roomHouseMapper.selectById(settlementRoomId);
                        if (Objects.nonNull(roomHouseDO)){
                            summaryDO.setSpace(roomHouseDO.getSpace());
                        }
                    }
                }
            }
            summaryDO.setActualRefundRent(actualRefundRent);
            summaryDO.setActualRefundDeposit(actualRefundDeposit);
            summaryDO.setActualRefundRentDeposit(actualRefundRent.add(actualRefundDeposit));

            // 实收租金合计 = 实收租金 - 实退租金
            summaryDO.setActualRentAmount(summaryDO.getActualRent().subtract(summaryDO.getActualRefundRent()));
            // 实收押金合计 = 实收押金 - 实退押金
            summaryDO.setActualDepositAmount(summaryDO.getActualDeposit().subtract(summaryDO.getActualRefundDeposit()));
            // 实收租金及押金合计 = 收租金押金小计 - 退租金及押金小计
            summaryDO.setActualRentDepositAmount(summaryDO.getActualRentDeposit().subtract(summaryDO.getActualRefundRentDeposit()));
            summaryList.add(summaryDO);
        }
        reportCollectionSummaryMapper.insertBatch(summaryList);
    }

    private List<ContractRoomDO> getContractListByParamList(List<FinanceMoneyFlowDTO> moneyFlowList,List<ContractSettlementDO> settlementList,List<ContractRoomDO> companyContractList){
        List<Long> contratIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(moneyFlowList)){
            contratIds = moneyFlowList.stream()
                    .map(FinanceMoneyFlowDTO::getContractId)
                    .distinct()
                    .collect(Collectors.toList());
        }
        if (CollectionUtils.isNotEmpty(settlementList)){
            List<Long> settlementRoomIds = settlementList.stream()
                    .filter(s -> !ContractSettlementTypeEnum.COMPANY_BATCH.getValue().equals(s.getSettlementType()))
                    .map(ContractSettlementDO::getContractId)
                    .distinct()
                    .collect(Collectors.toList());
            contratIds.addAll(settlementRoomIds);
            if (CollectionUtils.isNotEmpty(companyContractList)){
                List<Long> collect = companyContractList.stream().map(ContractRoomDO::getId).collect(Collectors.toList());
                contratIds.addAll(collect);
            }
        }
        // 去重
        Set<Long> uniqueSet = new LinkedHashSet<>(contratIds);
        contratIds = new ArrayList<>(uniqueSet);

        // 查询合同信息
        if (CollectionUtils.isNotEmpty(contratIds)){
            return contractRoomMapper.selectList(ContractRoomDO::getId, contratIds);
        }else {
            return null;
        }
    }

    private void handlerAll(List<FinanceMoneyFlowDTO> moneyFlowList,List<ContractSettlementDO> settlementList) {
        List<ContractRoomDO> companyContractList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(settlementList)){
            // 企业批量清算单
            List<Long> companyContractIds = settlementList.stream()
                    .filter(s -> ContractSettlementTypeEnum.COMPANY_BATCH.getValue().equals(s.getSettlementType()))
                    .map(ContractSettlementDO::getContractId)
                    .collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(companyContractIds)){
                companyContractList = contractRoomMapper.selectList(ContractRoomDO::getCompanyContractId, companyContractIds);
            }
        }
        // 合同信息
        List<ContractRoomDO> contractRoomList = getContractListByParamList(moneyFlowList, settlementList,companyContractList);
        if (CollectionUtils.isEmpty(contractRoomList)){
            log.error("未查询到合同信息");
            return;
        }

        List<Long> roomIds = contractRoomList.stream()
                .map(ContractRoomDO::getRoomId)
                .distinct()
                .collect(Collectors.toList());
        // 查询房源信息
        List<RoomHouseDO> roomHouseList = roomHouseMapper.selectByIds(roomIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            log.error("未查询到房源信息");
            return;
        }

        // 查询账单明细
        List<ContractOrderFeesDO> contractOrderFeesList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(moneyFlowList)){
            List<Long> orderIds = moneyFlowList.stream()
                    .map(FinanceMoneyFlowDTO::getOrderId)
                    .distinct()
                    .collect(Collectors.toList());
            contractOrderFeesList = contractOrderfeesMapper.selectByOrderIds(orderIds);
        }

        // 查询清算单明细
        List<ContractSettlementDetailDO> contractSettlementDetails = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(settlementList)){
            List<Long> settlementIds = settlementList.stream()
                    .map(ContractSettlementDO::getId)
                    .distinct()
                    .collect(Collectors.toList());
            contractSettlementDetails = contractSettlementDetailMapper.selectByOrderIds(settlementIds);
        }


        List<ReportCollectionSummaryDO> summaryList = new ArrayList<>();

        // 房间号+承租人 分组
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Map<String, List<FinanceMoneyFlowDTO>> moneyFlowMap = moneyFlowList.stream()
                .filter(m -> Objects.nonNull(m.getRoomId()))
                .collect(Collectors.groupingBy(m -> m.getRoomId() + "-" + m.getRenter() + "-" + m.getPayTime().format(formatter)));
        Map<String, List<ContractSettlementDO>> settlementMap = settlementList.stream()
                .filter(s -> Objects.nonNull(s.getRoomId()))
                .collect(Collectors.groupingBy(s -> s.getRoomId() + "-" + s.getCustomerName() + "-" + s.getCreateTime().format(formatter)));
        List<String> roomRenterList = new ArrayList<>();
        if (moneyFlowMap != null && !moneyFlowMap.isEmpty()){
            roomRenterList.addAll(new ArrayList<>(moneyFlowMap.keySet()));
        }
        if (settlementMap != null && !settlementMap.isEmpty()){
            roomRenterList.addAll(new ArrayList<>(settlementMap.keySet()));
        }
        // 去重
        Set<String> roomRenterSet = new LinkedHashSet<>(roomRenterList);
        roomRenterList = new ArrayList<>(roomRenterSet);

        for (String roomRenter : roomRenterList) {
            ReportCollectionSummaryDO summaryDO = new ReportCollectionSummaryDO();
            List<FinanceMoneyFlowDTO> moneyFlowDTOList = moneyFlowMap.get(roomRenter);
            String[] split = roomRenter.split("-");
            Long roomId = Long.valueOf(split[0]);
            String renter = split[1];
            summaryDO.setRoomId(roomId);
            summaryDO.setCustomerName(renter);

            Long contractId = null;
            summaryDO.setActualRent(BigDecimal.ZERO);
            summaryDO.setActualDeposit(BigDecimal.ZERO);
            summaryDO.setActualRentDeposit(BigDecimal.ZERO);
            summaryDO.setActualWater(BigDecimal.ZERO);
            summaryDO.setActualElectric(BigDecimal.ZERO);
            summaryDO.setActualPark(BigDecimal.ZERO);
            summaryDO.setActualOther(BigDecimal.ZERO);
            summaryDO.setActualFeeAmount(BigDecimal.ZERO);
            if (CollectionUtils.isNotEmpty(moneyFlowDTOList)){
                FinanceMoneyFlowDTO financeMoneyFlowDTO = moneyFlowDTOList.get(0);
                summaryDO.setRoomName(financeMoneyFlowDTO.getRoomName());
                summaryDO.setPaymentDate(financeMoneyFlowDTO.getTradeTime());
                contractId = financeMoneyFlowDTO.getContractId();
                // 实收租金、押金、水费、电费、停车费、其他杂费
                List<FinanceMoneyFlowDTO> orderList =
                        moneyFlowDTOList.stream()
                                .filter(m -> OrderTypeEnum.DEFAULT.getCode().equals(m.getOrderType()))
                                .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(orderList)){
                    BigDecimal actualRent = BigDecimal.ZERO;
                    BigDecimal actualDeposit = BigDecimal.ZERO;
                    for (FinanceMoneyFlowDTO moneyFlowDTO : orderList) {
                        actualRent = actualRent.add(moneyFlowDTO.getRentAmount()
                                .subtract(Objects.nonNull(moneyFlowDTO.getDiscountAmount())?moneyFlowDTO.getDiscountAmount():BigDecimal.ZERO)
                                .subtract(Objects.nonNull(moneyFlowDTO.getCouponDiscount())?moneyFlowDTO.getCouponDiscount():BigDecimal.ZERO));
                        actualDeposit = actualDeposit.add(moneyFlowDTO.getDepositAmount());
                    }
                    summaryDO.setActualRent(actualRent);
                    summaryDO.setActualDeposit(actualDeposit);
                    summaryDO.setActualRentDeposit(actualRent.add(actualDeposit));
                }
                List<FinanceMoneyFlowDTO> feeOrderList =
                        moneyFlowDTOList.stream()
                                .filter(m -> OrderTypeEnum.METER.getCode().equals(m.getOrderType()))
                                .collect(Collectors.toList());
                List<Long> feeOrderIds = feeOrderList.stream().map(FinanceMoneyFlowDTO::getId).collect(Collectors.toList());
                List<ContractOrderFeesDO> orderFeesList = contractOrderFeesList.stream()
                        .filter(f -> feeOrderIds.contains(f.getOrderId()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(orderFeesList)){
                    BigDecimal waterFee = BigDecimal.ZERO;
                    BigDecimal electFee = BigDecimal.ZERO;
                    BigDecimal parkFee = BigDecimal.ZERO;
                    BigDecimal otherFee = BigDecimal.ZERO;
                    for (ContractOrderFeesDO orderFeesDO : orderFeesList) {
                        if (orderFeesDO.getFeeName().contains("水费")){
                            waterFee = waterFee.add(orderFeesDO.getPaidAmount());
                        } else if (orderFeesDO.getFeeName().contains("电费")) {
                            electFee = electFee.add(orderFeesDO.getPaidAmount());
                        } else if (orderFeesDO.getFeeName().contains("停车费")) {
                            parkFee = parkFee.add(orderFeesDO.getPaidAmount());
                        } else {
                            otherFee = otherFee.add(orderFeesDO.getPaidAmount());
                        }
                    }
                    summaryDO.setActualWater(waterFee);
                    summaryDO.setActualElectric(electFee);
                    summaryDO.setActualPark(parkFee);
                    summaryDO.setActualOther(otherFee);
                    summaryDO.setActualFeeAmount(waterFee.add(electFee).add(parkFee).add(otherFee));
                }
            }

            // 清算单
            summaryDO.setActualRefundRent(BigDecimal.ZERO);
            summaryDO.setActualRefundDeposit(BigDecimal.ZERO);
            summaryDO.setActualRefundRentDeposit(BigDecimal.ZERO);
            if (CollectionUtils.isNotEmpty(contractSettlementDetails) && CollectionUtils.isNotEmpty(settlementList)){
                List<ContractSettlementDO> contractSettlementDOS = settlementMap.get(roomRenter);
                if (CollectionUtils.isNotEmpty(contractSettlementDOS)){
                    ContractSettlementDO contractSettlementDO = contractSettlementDOS.get(0);
                    summaryDO.setRoomName(contractSettlementDO.getRoomName());
                    contractId = contractSettlementDO.getContractId();
                    summaryDO.setPaymentDate(contractSettlementDO.getCreateTime());
                    // 实退租金、押金
                    List<ContractSettlementDetailDO> settlementRentDepositList = contractSettlementDetails.stream()
                            .filter(s -> (FlowTypeEnum.OUT.getCode().equals(s.getFlowType())) && s.getSettlementId().longValue() == contractSettlementDO.getId().longValue()
                                    && ((s.getFeeId().longValue() == 1L) || (s.getFeeId().longValue() == 2L)))
                            .collect(Collectors.toList());
                    BigDecimal actualRefundRent = BigDecimal.ZERO;
                    BigDecimal actualRefundDeposit = BigDecimal.ZERO;
                    for (ContractSettlementDetailDO contractSettlementDetailDO : settlementRentDepositList) {
                        if (1L == contractSettlementDetailDO.getFeeId().longValue()){
                            actualRefundRent = actualRefundRent.add(contractSettlementDetailDO.getRefundableAmount());
                        }
                        if (2L == contractSettlementDetailDO.getFeeId().longValue()){
                            actualRefundDeposit = actualRefundDeposit.add(contractSettlementDetailDO.getRefundableAmount());
                        }
                    }
                    summaryDO.setActualRefundRent(actualRefundRent);
                    summaryDO.setActualRefundDeposit(actualRefundDeposit);
                    summaryDO.setActualRefundRentDeposit(actualRefundRent.add(actualRefundDeposit));
                }
            }

            // 实收租金合计 = 实收租金 - 实退租金
            summaryDO.setActualRentAmount(summaryDO.getActualRent().subtract(summaryDO.getActualRefundRent()));
            // 实收押金合计 = 实收押金 - 实退押金
            summaryDO.setActualDepositAmount(summaryDO.getActualDeposit().subtract(summaryDO.getActualRefundDeposit()));
            // 实收租金及押金合计 = 收租金押金小计 - 退租金及押金小计
            summaryDO.setActualRentDepositAmount(summaryDO.getActualRentDeposit().subtract(summaryDO.getActualRefundRentDeposit()));

            // 合同信息
            Long finalContractId = contractId;
            ContractRoomDO contractRoomDO = contractRoomList.stream()
                    .filter(cr -> cr.getId().equals(finalContractId))
                    .findFirst().orElse(null);
            if (Objects.isNull(contractRoomDO)){
                continue;
            }
            summaryDO.setMemberId(contractRoomDO.getMemberId());
            summaryDO.setTenantId(contractRoomDO.getTenantId());
            // 房源信息
            RoomHouseDO roomHouseDO = roomHouseList.stream()
                    .filter(r -> r.getId().equals(summaryDO.getRoomId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            summaryDO.setSpace(roomHouseDO.getSpace());
            summaryList.add(summaryDO);
        }
//        // 校验重复
//        List<String> flowNoList = summaryList.stream().map(ReportFeeSummaryDO::getFlowNo).collect(Collectors.toList());
//        List<Long> existFlowNos = reportFeeSummaryMapper.selectExistOrder(flowNoList);
//        if (CollectionUtils.isNotEmpty(existFlowNos)){
//            // 过滤重复数据后插入
//            summaryList = summaryList.stream().filter(s -> !existFlowNos.contains(s.getOrderId())).collect(Collectors.toList());
//        }
        reportCollectionSummaryMapper.insertBatch(summaryList);
    }



    /**
     * 应收已收租金核对表
     */
    @XxlJob("receivable-check")
    @TenantIgnore
    public void receivableCheckExecute() {
        //默认获取昨天账单流水
        String params = XxlJobHelper.getJobParam();
        CollectionHandlePO paramPo = new CollectionHandlePO();
        if(StringUtils.isNotBlank(params)){
            try {
                paramPo = JSONObject.parseObject(params, CollectionHandlePO.class);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }else {
            paramPo.setMinusDay(1);
        }
        // 默认合同账单
        paramPo.setType(0);
        Long totalNum = financeMoneyFlowMapper.countSummaryByParam(paramPo);
        if (totalNum <= 1000) {
            List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
            if (CollectionUtils.isNotEmpty(moneyFlowList)){
                handlerReceivableCheck(moneyFlowList);
            }
        } else {
            //分1000一批处理
            int num = totalNum.intValue()/1000 + 1 ;
            CountDownLatch latch = new CountDownLatch(num);
            for (int i = 0; i < num; i++) {
                paramPo.setPageNo(i * 1000);
                paramPo.setPageSize(1000);
                List<FinanceMoneyFlowDTO> moneyFlowList = financeMoneyFlowMapper.selectSummaryByParam(paramPo);
                ThreadPoolUtils.poolExecutor.execute(()->{
                    handlerReceivableCheck(moneyFlowList);
                    latch.countDown();
                });
            }
            try {
                log.info("---------------处理应收已收租金核对表完成-------------");
                latch.await();
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }

        }
    }

    private void handlerReceivableCheck(List<FinanceMoneyFlowDTO> moneyFlowList) {
        List<Long> contratIds = moneyFlowList.stream()
                .map(FinanceMoneyFlowDTO::getContractId)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contratIds)){
            return;
        }
        // 查询合同信息
        List<ContractRoomDO> contractRoomList = contractRoomMapper.selectList(ContractRoomDO::getId, contratIds);
        if (CollectionUtils.isEmpty(contractRoomList)){
            return;
        }
        List<Long> roomIds = contractRoomList.stream()
                .map(ContractRoomDO::getRoomId)
                .distinct()
                .collect(Collectors.toList());
        // 查询房源信息
        List<RoomHouseDO> roomHouseList = roomHouseMapper.selectByIds(roomIds);
        if (CollectionUtils.isEmpty(roomHouseList)){
            return;
        }
        List<ReportReceivableCheckDO> summaryList = new ArrayList<>();
        for (FinanceMoneyFlowDTO moneyFlow : moneyFlowList) {
            ReportReceivableCheckDO summaryDO = new ReportReceivableCheckDO();
            summaryDO.setOrderId(moneyFlow.getOrderId());
            summaryDO.setFlowNo(moneyFlow.getFlowNo());
            summaryDO.setPayMethod(moneyFlow.getPayMethod());
            summaryDO.setPaymentDate(moneyFlow.getTradeTime());
            summaryDO.setTenantId(moneyFlow.getTenantId());
            summaryDO.setStartTime(moneyFlow.getStartTime());
            summaryDO.setEndTime(moneyFlow.getEndTime());
            summaryDO.setDeadlinePayTime(moneyFlow.getDeadlinePayTime());
            // 应收租金
            BigDecimal receivableRent = moneyFlow.getRentAmount()
                    .subtract(Objects.nonNull(moneyFlow.getDiscountAmount())?moneyFlow.getDiscountAmount():BigDecimal.ZERO)
                    .subtract(Objects.nonNull(moneyFlow.getCouponDiscount())?moneyFlow.getCouponDiscount():BigDecimal.ZERO);
            summaryDO.setReceivableRent(receivableRent);
            // 已收租金
            summaryDO.setActualRent(moneyFlow.getTradeAmount());
            // 预收租金
            summaryDO.setAdvanceRent(BigDecimal.ZERO);
            if (summaryDO.getDeadlinePayTime().compareTo(summaryDO.getPaymentDate().toLocalDate()) > 0){
                summaryDO.setAdvanceRent(moneyFlow.getTradeAmount());
            }
            // 未收租金
            BigDecimal uncollectedRent = summaryDO.getReceivableRent().subtract(summaryDO.getActualRent());
            uncollectedRent = uncollectedRent.compareTo(BigDecimal.ZERO) > 0 ? uncollectedRent : BigDecimal.ZERO;
            summaryDO.setUncollectedRent(uncollectedRent);

            // 合同信息
            ContractRoomDO contractRoomDO = contractRoomList.stream()
                    .filter(cr -> cr.getId().equals(moneyFlow.getContractId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(contractRoomDO)){
                continue;
            }
            summaryDO.setRoomId(contractRoomDO.getRoomId());
            summaryDO.setRoomName(contractRoomDO.getRoomName());
            summaryDO.setCustomerName(contractRoomDO.getCustomerName());
            summaryDO.setMemberId(contractRoomDO.getMemberId());

            // 房源信息
            RoomHouseDO roomHouseDO = roomHouseList.stream()
                    .filter(r -> r.getId().equals(contractRoomDO.getRoomId()))
                    .findFirst().orElse(null);
            if (Objects.isNull(roomHouseDO)){
                continue;
            }
            summaryDO.setSpace(roomHouseDO.getSpace());

            summaryList.add(summaryDO);
        }

        reportReceivableCheckMapper.insertBatch(summaryList);
    }

}